local gamelib = require "club.threecard.gamelib"
local Ease = CS.DG.Tweening.Ease

local column = {}

local log = gamelib.logging.get("column")

local function do_stop(self)
    local moveCount = #self.elements;

    for index, element in ipairs(self.elements) do
        local sequence = CS.DG.Tweening.DOTween.Sequence();
        sequence:Append(element.transform:DOLocalMoveY(element.transform.localPosition.y-100, self.speed));
        sequence:Append(element.transform:DOLocalMoveY(element.transform.localPosition.y, self.speed));
        sequence:OnComplete(function()
            moveCount = moveCount - 1;
            if moveCount == 0 then
                self.stop_to_overHandler();
            end
        end)
    end
end

-- 随缘停止，不保证停止的时间
----local function do_stop(self)
--end

-- 立即停止,保证停止的时间固定
-- 把屏幕外的第一个元素改变成目标元素，保证最后的元素相对位置不变.
local function do_stop_immediate(self)
    if self.stop_to_index == nil then
        log.warn("还没有停下的目标位置");
        return;
    end

    for i = 1, #self.config.symbol_indexs do
        self.elements[i].index = self.stop_to_index + i - self.config.stop_baseline;
        if self.elements[i].index <= 0 then
            self.elements[i].index = #self.config.symbol_indexs + self.elements[i].index;
        end

        if self.elements[i].index > #self.config.symbol_indexs then
            self.elements[i].index = self.elements[i].index - #self.config.symbol_indexs;
        end

        local id = self.config.symbol_indexs[self.elements[i].index]
        local symbol = self.symbol_map[id];
        self.elements[i]:change_config(symbol);
    end

    for _, element in ipairs(self.elements) do
        element:on_over_view();
    end
end


local function do_spin(self, ease)
    ease = ease or Ease.Linear;
    local moveCount = #self.elements;
    for index, element in ipairs(self.elements) do
        if index > self.config.last_on_port or index < self.config.first_on_port-1 then
            element:on_over_view();
        else
            element:on_view_port();
        end

        local nextElement = self.elements[index + 1];
        if nextElement then
            element.transform
            :DOLocalMoveY(nextElement.transform.localPosition.y, self.speed)
            :SetEase(ease)
            :OnComplete(function()
                if self.shutdowning then
                    return;
                end

                moveCount = moveCount - 1;
                if moveCount == 0 then
                    if self.stop_to_index then
                        if self.elements[self.config.stop_baseline].index == self.stop_to_index
                        and self.pass_count <= 0 then
                            do_stop(self);
                        else
                            self.pass_count = self.pass_count - 1;
                            if self.pass_count == 0 then
                                do_stop_immediate(self);
                            end
                            if self.elements[self.config.stop_baseline].index == self.stop_to_index
                            and self.pass_count <= 0 then
                                do_stop(self);
                            else
                                do_spin(self)
                            end
                        end
                    else
                        do_spin(self);
                    end
                end
            end)
        else
            element.transform.localPosition = self.elements[1].transform.localPosition
            moveCount = moveCount - 1;
        end
    end

    local lastElement = self.elements[#self.elements];
    table.remove(self.elements);
    table.insert(self.elements, 1, lastElement);
end

function column:start()
    if self.running then
        return;
    end

    self.running = true;

    do_spin(self, Ease.InBack);
end

function column:stop(index, overHandler)
    self.pass_count = self.config.on_result_pass_count or 7;

    self.stop_to_index = index;
    self.stop_to_overHandler = function()
        for _, element in ipairs(self.elements) do
            element:on_stop();
        end

        self.stop_to_index = nil;
        self.running = false;
        if overHandler then
            overHandler();
        end
        if self.index > 6 then
            gamelib.log.warn("reel stop 没有音效 index"..self.index);
            return;
        end

        self.machine.sfx["slots_stop_seta_"..self.index]();
    end;
end

function column:stop_immediate()
    if not self.running then
        return;
    end

    self.pass_count = 0;
    do_stop_immediate(self);
end

function column:shutdown()
    if not self.running then
        return;
    end

    self.shutdowning = true;
    for _, element in ipairs(self.elements) do
        element.transform:DOKill(true);
    end
    
    self.shutdowning = false;
    self.running = false;
end

function column:load()
    for _, element in ipairs(self.elements) do
        element:load();
    end
end

function column:release()
    for _, element in pairs(self.elements) do
        element:release();
    end
end

local slotlib = require "club.threecard.slotlib"
local element = slotlib.require "element"

function column.new(machine, index, config, symbol_map)
    local self = {};
    self.machine = machine;
    self.index = index;
    self.config = config;
    self.symbol_map = symbol_map;

    self.elements = {};
    self.speed = config.speed;
    
    for element_index, symbol_index in ipairs(config.symbol_indexs) do
        local symbol = symbol_map[symbol_index];
        if symbol == nil then
            gamelib.log.error("客户端没有找到symbol配置："..symbol_index);
        end
        table.insert(self.elements, element.new(symbol, element_index, machine.config.symbol_width, machine.config.symbol_height));
    end
    return setmetatable(self, {__index = column});
end

return column